package eatwatch;

import javax.microedition.io.Connector;
import javax.microedition.io.file.FileConnection;
import javax.microedition.rms.*;

import java.io.*;
import java.util.*;
import javax.microedition.midlet.MIDlet;
import javax.microedition.lcdui.*;

public final class EatWatch extends MIDlet implements CommandListener, Runnable
{
	public static 	MIDlet			Instance		= null;
	public	 		FormDailyIntake	mDailyIntake	= null;

	// common elements
    private final 	Command 		cmdExit  		= new Command ("Exit", Command.EXIT, 0);
    private final 	Command 		cmdBack  		= new Command ("Back", Command.BACK, 0);

    // main menu
    private final   String[] 		elements 		= {"Greutate", "Date", "Calorii", "Consum azi", "Situatie azi", "Export", "Import"};
    private final   List			lstMainMenu     = new List("Eat Watch", List.IMPLICIT, elements, null);

    // weight entry form
    private final   Form			frmWeightEntry  = new Form ("Greutate");
    private final 	TextField 		txtWeight 		= new TextField ("Greutate", "", 4, TextField.DECIMAL);
    private final   DateField   	dtfDate         = new DateField (null, DateField.DATE_TIME);
    private final 	Command 		cmdAdd  		= new Command ("Adauga", Command.OK, 0);

	// list data
	private final   List			lstData         = new List("Greutate", List.IMPLICIT);
    private final 	Command 		cmdDelete  		= new Command ("Sterge", Command.ITEM, 0);
	private 		Hashtable		mIds			= null;

	private 		FormCalories 	mFormCalories 	= null;
	private 		FormDailyReport	mDailyReport 	= null;

    // other variables
    private 		boolean 	isInitialized 	= false;
	public static	final	IDatabase	mDatabase		= new DatabaseRecordStore ();

	public EatWatch ()
	{
		Instance = this;
		mFormCalories = new FormCalories (this);
		mDailyIntake  = new FormDailyIntake (this);
		mDailyReport  = new FormDailyReport (this);
	}

    protected void destroyApp(boolean unconditional) {}
    protected void pauseApp() {}

    protected void startApp ()
    {
        if (isInitialized)
            return;

		InitMainMenu ();
		InitWeitghEntry ();
		InitData ();

        Display.getDisplay (this).setCurrent (lstMainMenu);
        isInitialized = true;
    }

    public void commandAction(Command c, Displayable d)
    {
		// common comands
        if (c == cmdExit) {
            destroyApp(false);
            notifyDestroyed();
            return;
        }
        // main menu commands
        else if (d == lstMainMenu) {
			if (c == List.SELECT_COMMAND) {
				if (lstMainMenu.getSelectedIndex () == 0) {// Weight Entry
					Display.getDisplay (this).setCurrent (frmWeightEntry);
					dtfDate.setDate (Calendar.getInstance ().getTime ());
				}
				else if (lstMainMenu.getSelectedIndex () == 1) {// Data
					Display.getDisplay (this).setCurrent (lstData);
					FillData ();
				}
				else if (lstMainMenu.getSelectedIndex () == 2) {// Calories
					mFormCalories.Show (d);
				}
				else if (lstMainMenu.getSelectedIndex () == 3) {// DailyIntake
					mDailyIntake.ShowAdd (d);
				}
				else if (lstMainMenu.getSelectedIndex () == 4) {// DailyReport
					mDailyReport.Show (d);
				}
				else if (lstMainMenu.getSelectedIndex () == 5) {
					new Thread(this).start();
				}
				else if (lstMainMenu.getSelectedIndex () == 6) {
					new Thread(this).start();
				}
			}
		}
		// weight entry commands
        else if (d == frmWeightEntry) {
			if (c == cmdBack)
				Display.getDisplay (this).setCurrent (lstMainMenu);
			else if (c == cmdAdd) {
				if (txtWeight.getString ().length () == 0)
					return;
				AddWeight (txtWeight.getString (), dtfDate.getDate ());
				Display.getDisplay (this).setCurrent (lstMainMenu);
			}
		}
        else if (d == lstData) {
			if (c == cmdBack)
				Display.getDisplay (this).setCurrent (lstMainMenu);
			else if (c == cmdDelete) {
				mDatabase.Open ("weight");
				mDatabase.DeleteRecord (((Integer) mIds.get (new Integer (lstData.getSelectedIndex ()))).intValue ());
				mDatabase.Close ();
				FillData ();
			}
		}
    }

    private void InitWeitghEntry ()
    {
        frmWeightEntry.append (txtWeight);
        frmWeightEntry.append (dtfDate);
        frmWeightEntry.addCommand (cmdAdd);
        frmWeightEntry.addCommand (cmdBack);
        frmWeightEntry.setCommandListener (this);
	}

	private void InitMainMenu ()
	{
		lstMainMenu.addCommand (cmdExit);
		lstMainMenu.setCommandListener (this);
	}

	private void InitData ()
	{
		lstData.addCommand (cmdBack);
		lstData.addCommand (cmdDelete);
		lstData.setCommandListener (this);
	}

	private void AddWeight (String weight, Date date)
	{
		Record rec = new Record ();
		rec.SetField ("weight", new Float (Float.parseFloat (weight)));
		rec.SetField ("date", date);
		mDatabase.Open ("weight");
		mDatabase.AddRecord (rec);
		mDatabase.Close ();
	}

	private void FillData ()
	{
		lstData.deleteAll ();
		mIds = new Hashtable ();

		mDatabase.Open ("weight", "date DESC");
		Record rec = null;
		Calendar calendar = (Calendar)Calendar.getInstance();
		int idx = 0;
		while ((rec = mDatabase.ReadRecord ()) !=null) {
			mIds.put (new Integer (idx++), new Integer (rec.GetId ()));
			calendar.setTime ((Date)rec.GetField ("date"));
			lstData.append (((Float)rec.GetField ("weight")).toString () +
								"   " +
								calendar.get(Calendar.DAY_OF_MONTH) +
								"." +
								(calendar.get(Calendar.MONTH) + 1),
							null);
		}
		mDatabase.Close ();
		if (idx > 0)
			lstData.setSelectedIndex (0, true);
	}

	public void run ()
	{
		Import ();
	}

	private void Export ()
	{
		Export ("weight");
		Export ("weight_dd");
		Export ("calories");
		Export ("calories_dd");
		Export ("intake");
		Export ("intake_dd");
	}

	private void Import ()
	{
		Import ("weight");
		Import ("weight_dd");
		Import ("calories");
		Import ("calories_dd");
		Import ("intake");
		Import ("intake_dd");
	}

	private void Export (String table)
	{
		String _fileName = "file:///e:/" + table + ".dmp";
		FileConnection _fconn = null;
		try {
			_fconn = (FileConnection)Connector.open(_fileName);
			if (!_fconn.exists())
				_fconn.create();
			OutputStream os = _fconn.openOutputStream(_fconn.fileSize());
			RecordStore mRecordStore = null;
			RecordEnumeration mRecEnumeration = null;
			try {
				mRecordStore = RecordStore.openRecordStore (table, true);
				mRecEnumeration = mRecordStore.enumerateRecords (null, null, false);
			}
			catch (RecordStoreException ignore) { }

			try {
				while (mRecEnumeration.hasNextElement ())  {
					int recordId = mRecEnumeration.nextRecordId ();
					System.out.println ("recordId: " + recordId);
					byte[] data = mRecordStore.getRecord (recordId);
					int size = data.length;
					os.write (size);
					os.write (size >> 8);
					os.write (size >> 16);
					os.write (size >> 24);
					os.write(data);
				}
			}
			catch (RecordStoreException ignore) { }

			os.flush();
			os.close();

			_fconn.close () ;
System.out.println ("6");
		}
		catch (IOException ignore) {}
	}

	private void Import (String table)
	{
		String _fileName = "file:///e:/" + table + ".dmp";
		FileConnection _fconn = null;

		try {
			_fconn = (FileConnection)Connector.open(_fileName);
			if (!_fconn.exists())
				return;
			InputStream is = _fconn.openInputStream();

			RecordStore mRecordStore = null;
			try {
				mRecordStore = RecordStore.openRecordStore (table, true);
			}
			catch (RecordStoreException ignore) { }

			int rb = 0;
			while (-1 != (rb = is.read())) try {
				int size = rb;
				size += is.read () << 8;
				size += is.read () << 16;
				size += is.read () << 24;
				byte[] data = new byte[size];
				is.read(data);
				mRecordStore.addRecord (data, 0, data.length);
			}
			catch (RecordStoreException ignore) { }

			is.close();

			_fconn.close () ;
		}
		catch (Exception e) {
			System.out.println (e);
			e.printStackTrace ();
		}
	}
}
